package com.xiaobaibai.security.login.filter;

import com.alibaba.fastjson.JSON;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;

//@Component
public class No2MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    //抛弃
    /**
     * todo  我们本可以更方便,不用创完 然后去LoginConfig拼接的
     * todo  注意点:需要创建AuthenticationManagerBean,然后手动设置进本Filter
     *     @Bean
     *     public AuthenticationManager authenticationManagerBean() throws Exception {
     *         return super.authenticationManagerBean();
     *     }
     *
     * todo  最终抛弃   太麻烦  还不如自定继承总的,然后开始写
     *
     * 我们可以直接继承UsernamePasswordAuthenticationFilter
     * 1.对于要修改/login,好像无能为力,只能继承UserNamePasswordFilter的父类去改
     * 2.对于取参数重写attemptAuthentication即可
     */

    /**
     * 回顾了之前的security代码,之前对于登录是指定好对应的登录url,
     * 然后用security默认的 UsernamePasswordAuthenticationFilter 类去做捕获请求中的username+password
     * 我们去看源码:
     * private String usernameParameter = "username";
     * request.getParameter(this.usernameParameter);
     * 它是从请求中的参数获取,但是现在我要用@RequestBody Map<String,String> data这个接收,
     * 所以默认filter不对版,需要我们手写一个
     */

    private String usernameParameter = "username";
    private String passwordParameter = "password";
    private boolean postOnly = true;//是否只处理post请求

    public No2MyUsernamePasswordAuthenticationFilter() {
        //匹配login路径+指定方法
        super();
    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String str = "";
        String data = "";
        BufferedReader br = null;
        try {
            br = request.getReader();
            while ((str = br.readLine()) != null) {
                data += str;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String,String> filterLoginData = JSON.parseObject(data, Map.class);
        request.setAttribute("loginData",filterLoginData);


        String username = filterLoginData.get(usernameParameter);
        String password = filterLoginData.get(passwordParameter);
        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        this.setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

//    @Nullable
//    protected String obtainPassword(HttpServletRequest request) {
//        return request.getParameter(this.passwordParameter);
//    }
//
//    @Nullable
//    protected String obtainUsername(HttpServletRequest request) {
//        return request.getParameter(this.usernameParameter);
//    }

    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

//    public void setUsernameParameter(String usernameParameter) {
//        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
//        this.usernameParameter = usernameParameter;
//    }
//
//    public void setPasswordParameter(String passwordParameter) {
//        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
//        this.passwordParameter = passwordParameter;
//    }

//    public void setPostOnly(boolean postOnly) {
//        this.postOnly = postOnly;
//    }
//
//    public final String getUsernameParameter() {
//        return this.usernameParameter;
//    }
//
//    public final String getPasswordParameter() {
//        return this.passwordParameter;
//    }

}
